package Pages;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Vector;

import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.game.Sprite;

import Const.GConfig;
import Const.IDTouch;
import Core.KEY;
import Pages.sub.Move;
import Pages.sub.Step;


public class CPlayer {
	private Game gameMain; // ref

	public static int[][] arrMap; // map pos
	public Image imgBuffer; // img map buffer
	public Image imgTile; // tile of map buffer
	public int iTimeHideMap; // thoi gian an map
	public boolean isStep; // bat dau game
	public static Image[] imgMove; // focus, box, start, men
	public Move men; // nguoi di tim kho bau
	public Move start; // vi tri bat dau
	public Move focus; // vi tri di chuyen
	public Move box; // kho bau
	public Move glow; // vi tri sang
	public boolean hasBox; // lay duoc kho bau
	public static Image imgStep; // buoc di
	public Vector vStep; // vector buoc di
	private Image imgXuong;
	public static Image imgBoxSmall; // kho bau khi lay duoc

	public static int s_iMapY = 50;// 64; // ve map
	public static int s_iMapX = 10;// 71; // ve map

	public CPlayer(Game gameMain) {
		this.gameMain = gameMain;
	}

	public void initialize() { //gameMain.level = 5;
		try {
		if (imgBoxSmall == null) imgBoxSmall = Image.createImage("/boxSmall.png");
		if (imgStep == null) imgStep = Image.createImage("/step.png");
		if (arrMap == null) arrMap = new int[GConfig.k_iRow][GConfig.k_iCol];
		if (imgTile == null) imgTile = Image.createImage("/tile.png");
		if (imgXuong == null) imgXuong = Image.createImage("/skull3.png");
		if (imgBuffer == null) imgBuffer = Image.createImage(GConfig.k_iCol * GConfig.k_iCellWidth, GConfig.k_iRow * GConfig.k_iCellHigh);
		} catch (Exception e) {
			System.out.println("Load Image error: " + e.toString());
		}
		
		// actor image... 
		if (imgMove == null) {
			imgMove = new Image[17];
			for (int i = 0; i < imgMove.length; i++)
				if (imgMove[i] == null)
					try {
						imgMove[i] = Image.createImage("/kind" + i + ".png");
					} catch (IOException e) {
						System.out.println("Load imgKind error: "
								+ e.toString());
					}
		}
		if (men != null)
			men = null;
		if (focus != null)
			focus = null;
		if (start != null)
			start = null;
		if (glow != null)
			glow = null;
		if (box != null)
			box = null;
		
		try {
			loadMap();
		} catch (IOException e) {
			System.out.println("Load map error: " + e.toString());
		}
		createMapBuffer(false);
		
		hasBox = false;
		iTimeHideMap = GConfig.k_iTimeHideMap;
		isStep = false;
		
		if (vStep == null)
			vStep = new Vector();
		// khong ve khi tang level
		for (int i = 0; i < vStep.size(); i++) {
			Step sTemp = (Step) vStep.elementAt(i);
			sTemp.setTime(0);
		}
		
		// moi level them 2 buoc di
		addStep(GConfig.k_inStep);
		
		switch (gameMain.level) {
		case 1:
			start = new Move(409, 42, 2);
			box = new Move(392, 253, 1);
			break;
		case 2:
			start = new Move(412, 49, 2);
			box = new Move(410, 290, 1);
			break;
		case 3:
			start = new Move(414, 284, 2);
			box = new Move(418, 38, 1);
			break;
		case 4:
			start = new Move(405, 296, 2);
			box = new Move(407, 56, 1);
			break;
		}
		men = new Move(start.getX() + 20, start.getY() + 20, 5);
		men.setStep(10);
		men.setHasBox(hasBox);
		focus = new Move(men.getX(), men.getY(), 0);
		focus.setStep(10);
		glow = new Move(box.getX() - 20, box.getY() - 20, 2);
	}
	
	public void addStep(int iadd){
		if(iadd <= 0) return;
		int ib = 1 - (vStep.size() > 0 ? ((Step)vStep.lastElement()).getIndexImg() : 1);
		for (int i = 0; i < iadd; i++, ib = 1 - ib){
			vStep.addElement(new Step(0, 0, ib, 0, GConfig.k_iRight));
		}
	}
	
	public void paint(Graphics g) {
		paintMapBuffer(g);
		start.paint(g);
		for (int i = 0; i < vStep.size(); i++) {
			Step sTemp = (Step) vStep.elementAt(i);
			sTemp.paint(g);
		}
		if (!hasBox) {
			if (!gameMain.isGameWin)
				glow.paint(g);
			box.paint(g);
		}
		men.paint(g);
		focus.paint(g);
	}

	public void paintMapBuffer(Graphics g) {
		gameMain.map.drawMap(g);
	}

	public void update() {
		men.update();
		start.update();
		if (hasBox == false) {
			box.update();
			glow.update();
		}
		for (int i = 0; i < vStep.size(); i++) {
			Step sTemp = (Step) vStep.elementAt(i);
			sTemp.update();
		}
		if (men.isMove()) {
			checkCollisonMenFire();
			if (men.isMove()) {
				men.move();
				gameMain.map.goTo(men.getX() + men.getW()/2, men.getY() + men.getH()/2);
				// buoc chan
				if (Game.timeTick % 5 == 0) {
					Step sTemp;
					sTemp = (Step) vStep.lastElement();
					sTemp.setStep(men.getX(), men.getY(), sTemp.getIndexImg(),
							10, men.getSee());
					vStep.insertElementAt(sTemp, 0);
					vStep.removeElementAt(vStep.size() - 1);
				}
			}
		}
		if (!men.isHasBox() && men.getNumCollison() <= 0)
			checkBox();
		else if (men.isHasBox())
			checkGoHome();

		if(isStep){
			if (KEY.isPressed(KEY.RIGHT)) {
				focus.moveRight();
			} else if (KEY.isPressed(KEY.LEFT)) {
				focus.moveLeft();
			} else if (KEY.isPressed(KEY.DOWN)) {
				focus.moveDown();
			} else if (KEY.isPressed(KEY.UP)) {
				focus.moveUp();
			}
		}
	}

	public void checkCollisonMenFire() {
		int x, y, r, c, r1, r2, c1, c2, stepR, stepC;
		stepR = men.getStep() / GConfig.k_iCellHigh;
		stepC = men.getStep() / GConfig.k_iCellWidth;
		if (stepR <= 0)
			stepR = 1;
		if (stepC <= 0)
			stepC = 1;

		if (0 <= men.getDegree() && men.getDegree() < 90) {// xuong phai
			x = men.getX() + men.getW();
			y = men.getY() + men.getH();
		} else if (90 <= men.getDegree() && men.getDegree() < 180) {// xuong
			// trai
			x = men.getX();
			y = men.getY() + men.getH();
		} else if (180 <= men.getDegree() && men.getDegree() < 270) {// len trai
			x = men.getX();
			y = men.getY();
		} else if (270 <= men.getDegree() && men.getDegree() < 360) {// len phai
			x = men.getX() + men.getW();
			y = men.getY();
		} else {
			x = men.getX() + men.getW() / 2;
			y = men.getY() + men.getH() / 2;
		}
		r = y / GConfig.k_iCellHigh;
		c = x / GConfig.k_iCellWidth;
		r1 = r - stepR;
		r2 = r + stepR;
		if (r1 < 0)
			r1 = 0;
		else if (r1 >= GConfig.k_iRow)
			r1 = GConfig.k_iRow - 1;
		if (r2 < 0)
			r2 = 0;
		else if (r2 >= GConfig.k_iRow)
			r2 = GConfig.k_iRow - 1;
		c1 = c - stepC;
		c2 = c + stepC;
		if (c1 < 0)
			c1 = 0;
		else if (c1 >= GConfig.k_iCol)
			c1 = GConfig.k_iCol - 1;
		if (c2 < 0)
			c2 = 0;
		else if (c2 >= GConfig.k_iCol)
			c2 = GConfig.k_iCol - 1;

		for (r = r1; r <= r2 && men.getNumCollison() == 0; r++) {
			for (c = c1; c <= c2 && men.getNumCollison() == 0; c++) {
				if (checkCollision(men.getX(), men.getY(), men.getW(), men
						.getH(), c * GConfig.k_iCellWidth, r
						* GConfig.k_iCellHigh, GConfig.k_iCellWidth,
						GConfig.k_iCellHigh) == false) {
					if (arrMap[r][c] == 3) { // cham tuong
						men.setNumCollison(20);
						men.setMove(false);
						if(gameMain.arrItem[IDTouch.ITEM_CHAMTUONG - 3] <= 0){
							if(men.getNumLive() > 0)
								men.setNumLive(men.getNumLive() - 1);
							else
								gameMain.isGameOver = true;
						} else {
							gameMain.arrItem[IDTouch.ITEM_CHAMTUONG - 3]--;
						}
						// rot kho bau khi cham tuong
						if (men.isHasBox()) {
							Step sTemp = (Step) vStep.elementAt(1);
							box.setX(sTemp.getX());
							box.setY(sTemp.getY());
							glow.setX(box.getX() - 20);// cap nhat lai vi tri
							// quan sang
							glow.setY(box.getY() - 20);
							men.setHasBox(false);
							hasBox = false;
							men.setStep(10);
						}
					}
				}
			}
		}
	}

	public boolean checkCollision(int aX, int aY, int aW, int aH, int bX,
			int bY, int bW, int bH) {
		// System.out.println("-------CheckCollison: " + bX + ", " + bY);
		boolean isLeft = (bX <= aX && aX < bX + bW);
		boolean isRight = (aX <= bX && bX < aX + aW);
		boolean isUp = (bY <= aY && aY < bY + bH);
		boolean isDown = (aY <= bY && bY < aY + aH);
		if ((isLeft || isRight) && (isUp || isDown))
			return false; // va cham
		return true; // khong va cham
	}

	public void unloadPlayer() {
		imgBuffer = null;
		for (int i = 0; i < imgMove.length; i++)
			imgMove[i] = null;
		imgMove = null;
		imgTile = null;
		imgStep = null;
		imgBoxSmall = null;
	}

	public void loadMap() throws IOException {
		InputStream is = "".getClass().getResourceAsStream(
				"/map/map" + gameMain.level + ".dat");
		try {
			ByteArrayOutputStream bStrm = new ByteArrayOutputStream();
			int ch;
			while ((ch = is.read()) != -1) {
				bStrm.write(ch);
			}
			byte imageData[] = bStrm.toByteArray();
			int k = 0;
			for (int i = 0; i < GConfig.k_iRow; i++) {
				for (int j = 0; j < GConfig.k_iCol; j++) {
					arrMap[i][j] = imageData[k];
					k++;
					if(arrMap[i][j] == 4){
						start = new Move(j*10-30, i*10-30, 2);
					}else if(arrMap[i][j] == 5)
						box = new Move(j*10-10, i*10-20, 1);
				}
			}
			bStrm.close();
		} finally {
			if (is != null)
				is.close();
		}
	}

	public void createMapBuffer(boolean isHiding) {
		if (imgBuffer == null || imgTile == null)
			return;
		Graphics gMapBuffer = imgBuffer.getGraphics();
		int k = iTimeHideMap * 10;
		int index, x, y, r=0, c=0;
		Vector vec = new Vector();
		if (isHiding) {
			x = (start.getX() + start.getW() / 2);
			y = (start.getY() + start.getH() / 2);
			c = (int) Math.ceil(x / GConfig.k_iCellWidth);
			r = (int) Math.ceil(y / GConfig.k_iCellHigh);
		}
		gMapBuffer.setColor(0);
		gMapBuffer.fillRect(0, 0, GConfig.k_iCol*GConfig.k_iCellWidth, GConfig.k_iCol*GConfig.k_iCellHigh);
		for (int row = 0; row < GConfig.k_iRow; row++)
			for (int col = 0; col < GConfig.k_iCol; col++) {
				if (isHiding) {
					if ((c - k) < col && col < (c + k) && (r - k) < row	&& row < (r + k)) {
						index = arrMap[row][col];
					} else {
						continue;
					}
				} else
					index = arrMap[row][col];
				
				if(index == 4 || index == 5) index = 2;
				if(index == 6){
					index = 1;
					vec.addElement( new Integer((row<<16)|col));
				}
				
				gMapBuffer.drawRegion(imgTile, 0, (index - 1)
						* GConfig.k_iCellHigh, GConfig.k_iCellWidth,
						GConfig.k_iCellHigh, Sprite.TRANS_NONE, col
								* GConfig.k_iCellWidth, row
								* GConfig.k_iCellHigh, Graphics.TOP
								| Graphics.LEFT);
			}
		
		for(int i = 0; i < vec.size(); i++){
			Integer n = (Integer)vec.elementAt(i);
			int col = n.intValue() & 0xFF;
			int row = (n.intValue()>>16) & 0xFF;
			gMapBuffer.drawImage(imgXuong, col*10 - 10, row*10 - 20, 0);
		}
			
		//TODO: draw rock
		
		gMapBuffer.setColor(GConfig.k_iGirdColor);
		int nh = GConfig.k_iRow*GConfig.k_iCellHigh;
		int nw = GConfig.k_iCol*GConfig.k_iCellWidth;
		for(int j = 49; j < nh; j+=50)gMapBuffer.drawLine(0, j, GConfig.k_iCol*GConfig.k_iCellWidth, j);
		for(int i = 49; i < nw; i+=50)gMapBuffer.drawLine(i, 0, i, GConfig.k_iRow*GConfig.k_iCellHigh);
		gMapBuffer.drawLine(0, 0, GConfig.k_iCol*GConfig.k_iCellWidth, 0);
		gMapBuffer.drawLine(0, 0, 0, GConfig.k_iRow*GConfig.k_iCellHigh);
	}


	private void checkBox() {
		boolean isLeft = (men.getX() <= box.getX() && box.getX() < men.getX()
				+ men.getW());
		boolean isRight = (box.getX() <= men.getX() && men.getX() < box.getX()
				+ box.getW());
		boolean isTop = (men.getY() <= box.getY() && box.getY() < men.getY()
				+ men.getH());
		boolean isDown = (box.getY() <= men.getY() && men.getY() < box.getY()
				+ box.getH());

		if ((isLeft || isRight) && (isTop || isDown)) {
			// System.out.println("-------checkBox: Lay duoc kho bau!");
			hasBox = true;
			men.setHasBox(hasBox);
			men.setStep(8); // di cham khi co kho bau
		}
	}

	private void checkGoHome() {
		boolean isLeft = (men.getX() <= start.getX() && start.getX() < men.getX()+ men.getW());
		boolean isRight = (start.getX() <= men.getX() && men.getX() < start.getX()+ start.getW());
		boolean isTop = (men.getY() <= start.getY() && start.getY() < men.getY()+ men.getH());
		boolean isDown = (start.getY() <= men.getY() && men.getY() < start.getY()+ start.getH());

		if ((isLeft || isRight) && (isTop || isDown)) {
			// System.out.println("-------checkGoHome: Ve dich!");
			men.setHasBox(false);
			box.setX(start.getX());
			box.setY(start.getY());
			hasBox = false;
			if (gameMain.level == gameMain.MAX_LEVEL) {
				gameMain.isFinishGame = true;
			} else {
				createMapBuffer(false);
				gameMain.isGameWin = true;
			}
		}
	}
}
